package org.ling.xuan.util;

import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.ling.xuan.exception.HttpException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpCookiesClient {

    private static HttpClientBuilder httpClientBuilder;
    private static PoolingHttpClientConnectionManager poolingHttpClientConnectionManager;
    private static final RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
    // 创建cookie store的本地实例
    BasicCookieStore cookieStore = new BasicCookieStore();
    // 创建HttpClient上下文
    HttpClientContext context = HttpClientContext.create();
    // 创建一个HttpClient
    CloseableHttpClient httpClient = httpClientBuilder.setDefaultCookieStore(cookieStore).build();

    /**
     * 保证全局只通过一个builder去创建client
     */
    public static void init() {
        poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(800);// 设置每个路由基础的连接
        poolingHttpClientConnectionManager.setMaxTotal(1000);//设置最大连接数//cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute);// 设置目标主机的最大连接数
        httpClientBuilder = HttpClients.custom().setConnectionManager(poolingHttpClientConnectionManager).setDefaultRequestConfig(globalConfig);
    }

    public String doGet(String url, Map<String, String> header) throws HttpException {
        HttpGet get = new HttpGet(url);
        CloseableHttpResponse res = null;
        String s = null;
        if (header != null) {
            for (String key : header.keySet()) {
                get.setHeader(key, header.get(key));
            }
        }
        try {
            res = httpClient.execute(get, context);
            s = EntityUtils.toString(res.getEntity(), "UTF-8");
        } catch (IOException e) {
            throw new HttpException("请求失败：" + url);
        } finally {
            if (res != null) {
                try {
                    res.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return s;
    }

    public String doGet(String url, Map<String, Object> params, Map<String, String> header) throws HttpException {

        UrlEntity urlEntity = UrlUtil.parse(url);
        urlEntity.addParam(params);
        url = urlEntity.toUrl();
        HttpGet get = new HttpGet(url);
        CloseableHttpResponse res = null;
        String s = null;
        if (header != null) {
            for (String key : header.keySet()) {
                get.setHeader(key, header.get(key));
            }
        }
        try {
            res = httpClient.execute(get, context);
            s = EntityUtils.toString(res.getEntity(), "UTF-8");
        } catch (IOException e) {
            throw new HttpException("请求失败：" + url);
        } finally {
            if (res != null) {
                try {
                    res.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return s;
    }

    //application/x-www-form-urlencoded
    public String doPost(String url, Map<String, Object> param, Map<String, String> header) throws HttpException {

        CloseableHttpResponse response = null;
        HttpPost httpPost = new HttpPost(url);
        String s = null;
        if (header != null) {
            for (String key : header.keySet()) {
                httpPost.setHeader(key, header.get(key));
            }
        }
        try {
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, (String) param.get(key)));
                }
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
            response = httpClient.execute(httpPost, context);
            s = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (IOException e) {
            throw new HttpException("请求失败：" + url);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return s;
    }

    //application/json
    public String doPostJson(String url, String json, Map<String, String> header) throws HttpException {
        CloseableHttpResponse response = null;
        HttpPost httpPost = new HttpPost(url);
        String s = null;
        try {
            if (header != null) {
                for (String key : header.keySet()) {
                    httpPost.setHeader(key, header.get(key));
                }
            }
            StringEntity entity = new StringEntity(json);
            entity.setContentType("application/json;charset=utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost, context);
            s = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (IOException e) {
            throw new HttpException("请求失败：" + url);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return s;
    }

}
